import gradio as gr
import os
import time
from openai import OpenAI
import json
import uvicorn
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Optional, List, Dict, Any

# --- 配置部分 ---
# 从环境变量或直接设置您的百度AI API Key
BAIDU_API_KEY = os.environ.get("BAIDU_API_KEY", "xxx")  # 百度API Key
BAIDU_BASE_URL = "https://aistudio.baidu.com/llm/lmapi/v3"
MODEL_NAME = "ernie-4.5-turbo-vl"  # 百度模型

# 作物类型与对应问题的映射，用于更精准的问题类型推荐
CROP_PROBLEMS = {
    "小麦": ["锈病防治", "蚜虫防治", "倒伏问题", "施肥建议", "灌溉管理", "其他问题"],
    "水稻": ["稻瘟病防治", "螟虫防治", "倒伏问题", "施肥建议", "水分管理", "其他问题"],
    "玉米": [
        "大斑病防治",
        "玉米螟防治",
        "秃尖问题",
        "施肥建议",
        "灌溉管理",
        "其他问题",
    ],
    "大豆": [
        "根腐病防治",
        "食心虫防治",
        "落花落荚",
        "施肥建议",
        "灌溉管理",
        "其他问题",
    ],
    "棉花": [
        "枯萎病防治",
        "棉铃虫防治",
        "蕾铃脱落",
        "施肥建议",
        "灌溉管理",
        "其他问题",
    ],
    "蔬菜": ["霜霉病防治", "蚜虫防治", "畸形生长", "施肥建议", "灌溉管理", "其他问题"],
    "水果": ["果实病害", "虫害防治", "着色问题", "施肥建议", "灌溉管理", "其他问题"],
    "果树": ["枝干病害", "叶部病害", "落花落果", "施肥建议", "修剪管理", "其他问题"],
    "茶叶": ["叶部病害", "虫害防治", "品质问题", "施肥建议", "采摘管理", "其他问题"],
    "其他": ["病虫害防治", "施肥建议", "灌溉管理", "生长异常", "收获储存", "其他问题"],
}

# 初始化 OpenAI 客户端以兼容百度API
client = OpenAI(
    api_key=BAIDU_API_KEY,
    base_url=BAIDU_BASE_URL,
)


# --- 核心处理函数 (返回字典，供 API 使用) ---
def generate_agri_advice_core(
    crop_type, problem_type, growth_stage, description="", region="", photos=[]
):
    """
    根据用户输入生成农业建议的核心逻辑。
    返回一个字典: {"success": bool, "result": str} 或 {"success": bool, "error": str}
    """
    # 构建发送给AI的指令(Prompt)
    prompt = f"""
你是一位资深的农业专家，拥有丰富的作物种植和病虫害防治经验。请根据以下信息，为农户提供专业的农业建议：

种植信息：
- 作物类型: {crop_type}
- 生长阶段: {growth_stage}
- 所在地区: {region if region else '未明确'}
- 问题类型: {problem_type}
- 问题描述: {description if description else '未提供详细描述'}

请结合你的专业知识，提供详细、实用的解决方案，内容应包括：

1. 问题分析：
   - 可能的原因和诊断
   - 问题的严重程度评估

2. 解决方案：
   - 具体的处理方法和步骤
   - 推荐使用的农药、肥料或其他产品（如有）
   - 操作注意事项和安全提示

3. 预防措施：
   - 如何避免类似问题再次发生
   - 日常管理建议

4. 其他相关建议：
   - 针对当前生长阶段的特别提示
   - 与地区相关的适应性建议

请确保你的回答专业、准确、易懂，并以清晰的结构呈现。建议语言简洁明了，让农户能够轻松理解和操作。
"""

    try:
        # 构建消息列表
        messages = [{"role": "user", "content": prompt}]

        # 处理图片 - 只在有有效图片时添加说明
        # 过滤掉空值或无效图片路径
        valid_photos = [p for p in photos if p]

        # 如果有有效图片，添加图片信息提示
        if valid_photos:
            messages[0][
                "content"
            ] += f"\n用户还提供了{len(valid_photos)}张相关图片作为参考，请结合图片内容进行分析。"

        # 调用百度AI API
        completion = client.chat.completions.create(
            model=MODEL_NAME,
            messages=messages,
            stream=False,
            temperature=0.6,  # 适当调整创造性
        )

        # 获取AI回复内容
        ai_response = completion.choices[0].message.content
        return {"success": True, "result": ai_response}
    except Exception as e:
        # 错误处理
        print(f"调用AI API时出错: {e}")
        return {"success": False, "error": f"分析失败：{str(e)}"}


# --- 用于 Gradio 界面的包装函数 (返回字符串) ---
def generate_agri_advice_for_gradio(
    crop_type,
    problem_type,
    growth_stage,
    description="",
    region="",
    photo=None,
    progress=gr.Progress(),
):
    progress(0, desc="正在准备分析...")
    time.sleep(0.5)

    # 处理图片
    if photo is None:
        photos = []
    else:
        photos = [photo]

    progress(0.3, desc="正在分析您的问题...")
    result_dict = generate_agri_advice_core(
        crop_type, problem_type, growth_stage, description, region, photos
    )

    progress(0.8, desc="正在整理建议...")
    time.sleep(0.5)
    progress(1.0, desc="完成")

    if result_dict["success"]:
        return result_dict["result"]
    else:
        return f"抱歉，生成建议时遇到了问题：{result_dict['error']}\n请稍后重试。"


# 更新问题类型选项
def update_problem_types(crop_type):
    return gr.Dropdown(
        choices=CROP_PROBLEMS.get(crop_type, CROP_PROBLEMS["其他"]),
        value=CROP_PROBLEMS.get(crop_type, CROP_PROBLEMS["其他"])[0],
    )


# --- Gradio界面定义 ---
def gradio_interface():
    """创建Gradio界面用于测试或直接使用"""
    with gr.Blocks(
        title=" 智农助手 - 智能农业顾问",
        theme=gr.themes.Soft(),
    ) as demo:
        gr.Markdown("## 🌱智农助手 - 智能农业顾问")
        gr.Markdown("输入您的种植信息，获取专业的农业建议和解决方案")

        # 存储历史记录
        history_state = gr.State([])

        with gr.Row():
            with gr.Column(scale=2):
                crop_type = gr.Dropdown(
                    label="作物类型", choices=list(CROP_PROBLEMS.keys()), value="小麦"
                )

                problem_type = gr.Dropdown(
                    label="问题类型",
                    choices=CROP_PROBLEMS["小麦"],
                    value=CROP_PROBLEMS["小麦"][0],
                )

                # 当作物类型改变时，更新问题类型选项
                crop_type.change(
                    fn=update_problem_types, inputs=[crop_type], outputs=[problem_type]
                )

                growth_stage = gr.Dropdown(
                    label="生长阶段",
                    choices=[
                        "播种期",
                        "发芽期",
                        "幼苗期",
                        "生长期",
                        "开花期",
                        "结果期",
                        "成熟期",
                        "收获期",
                    ],
                    value="生长期",
                )

                region = gr.Textbox(
                    label="种植地区 (可选)", placeholder="例如：山东省临沂市"
                )

                description = gr.Textbox(
                    label="问题描述",
                    placeholder="请详细描述您遇到的问题，例如：叶子出现黄色斑点，生长缓慢...",
                    lines=4,
                )

                photo = gr.Image(
                    label="上传图片",
                    type="pil",  # 使用 PIL 图像对象，避免 filepath 为空的问题
                    height=200,
                    value=None,
                    # tooltip="建议上传问题部位的清晰照片，有助于更准确的诊断"
                )

                btn = gr.Button("获取专业建议", variant="primary")

                # 清除按钮
                clear_btn = gr.Button("清除输入", variant="secondary")

            with gr.Column(scale=3):
                output = gr.Markdown(label="农业专家建议", height=400)

        # 设置按钮点击事件
        btn.click(
            fn=generate_agri_advice_for_gradio,
            inputs=[crop_type, problem_type, growth_stage, description, region, photo],
            outputs=[output],
        )

        # 清除按钮事件
        clear_btn.click(
            fn=lambda: ("小麦", CROP_PROBLEMS["小麦"][0], "生长期", "", "", None, ""),
            inputs=[],
            outputs=[
                crop_type,
                problem_type,
                growth_stage,
                description,
                region,
                photo,
                output,
            ],
        )

        # 添加使用说明和示例
        with gr.Accordion("使用指南", open=False):
            gr.Markdown(
                """
            ### 如何获得更精准的建议？
            1. 准确选择作物类型和当前生长阶段
            2. 详细描述问题症状，包括出现时间、分布情况等
            3. 上传清晰的问题部位照片（如病叶、果实等）
            4. 提供种植地区信息，以便获得适应当地气候的建议
            
            ### 示例
            - 作物类型：小麦
            - 生长阶段：生长期
            - 问题类型：锈病防治
            - 描述：叶片上出现黄褐色粉末状斑点，从下部叶片开始出现，已持续3天
            - 地区：河南省郑州市
            """
            )

        gr.Markdown(
            """
        ---
        > 注意：本工具提供的建议仅供参考，重大农业决策请咨询当地农业技术人员
        """
        )

    return demo


# --- FastAPI 应用和 API 端点定义 ---

# 1. 创建 FastAPI 应用实例
app = FastAPI(
    title="智农助手API",
    description="提供农业建议的AI服务接口",
)


# 2. 定义请求体模型
class AgriAdviceRequest(BaseModel):
    crop_type: str
    problem_type: str
    growth_stage: str
    description: Optional[str] = ""
    region: Optional[str] = ""
    # 图片字段在实际应用中可能需要特殊处理，这里仅作为示例
    photos: Optional[List[str]] = []


# 3. 定义API端点
@app.post("/api/advice", summary="生成农业建议")
async def api_generate_advice(request: AgriAdviceRequest):
    """API端点：接收JSON请求，返回AI生成的农业建议"""
    result = generate_agri_advice_core(
        request.crop_type,
        request.problem_type,
        request.growth_stage,
        request.description,
        request.region,
        request.photos,  # 这里会自动处理空列表情况
    )
    if result["success"]:
        return result
    else:
        raise HTTPException(status_code=500, detail=result["error"])


# 4. 获取支持的作物类型和问题类型
@app.get("/api/supported-types", summary="获取支持的作物类型和问题类型")
async def get_supported_types():
    """返回支持的作物类型及其对应的问题类型"""
    return {"crop_problems": CROP_PROBLEMS}


# 5. 健康检查端点
@app.get("/health", summary="健康检查")
async def health_check():
    return {"status": "healthy", "service": "智农助手API", "timestamp": time.time()}


# --- 应用启动逻辑 ---
demo = gradio_interface()
app = gr.mount_gradio_app(app=app, blocks=demo, path="/")  # 将 Gradio 界面挂载到根路径

if __name__ == "__main__":
    print("🚀 启动智农助手服务...")
    print("📱 Gradio 界面访问地址: http://localhost:7860")
    print("💻 FastAPI 文档地址: http://localhost:7860/docs")
    print("-" * 50)

    # 使用 uvicorn 启动应用
    uvicorn.run(app, host="0.0.0.0", port=7860)
